package org.molehill
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display3D.Context3D;
	import flash.display3D.Context3DProgramType;
	import flash.display3D.Context3DTextureFormat;
	import flash.display3D.IndexBuffer3D;
	import flash.display3D.textures.Texture;
	import flash.geom.Matrix3D;
	import flash.geom.Point;
	import flash.geom.Rectangle;

	public class SpriteBIGMoleHill implements ISpriteMoleHill
	{
		private var _x:Number;
		private var _y:Number;
		private var _width:Number;
		private var _height:Number;
		private var _widthMolehill:int;
		private var _heightMolehill:int;
		private var _scaleX:Number;
		private var _scaleY:Number;
		private var _alpha:Number;
		private var _url:String;
		public var viewMatrix:Matrix3D;
		
		private var _context:Context3D;
		private var _matrix:Matrix3D;
		private var _bitmapdata:BitmapData;
		private var _blockBitmapV:Vector.<Vector.<Object>>;
		private var _texture:Texture;
		
		private var _wNum:int;
		private var _hNum:int;
		
		public var indexBuffer:IndexBuffer3D;
		
		public var viewRec:Rectangle;
		
		public function SpriteBIGMoleHill(context:Context3D)
		{
			_context    = context;
			_matrix     = new Matrix3D();
			_x = 0;
			_y = 0;
			_scaleX = 0;
			_scaleY = 0;
			_alpha = 1;
			viewRec = new Rectangle;
		}
		
		private function getWorldTransform(obj:Object):Matrix3D
		{
			_matrix.identity();
			_matrix.appendScale(obj.w * 0.5, obj.h * 0.5, 1);
			_matrix.appendTranslation((obj.w / 2) + x + obj.x, (obj.h / 2) + y + obj.y, 0);
			return _matrix;
		}
		
		public function render():void{
			for(var i:int=0;i<_wNum;i++){
				for(var j:int=0;j<_hNum;j++){
					var obj:Object = _blockBitmapV[i][j];
					if(obj.x>viewRec.x+viewRec.width || obj.x+obj.w < viewRec.x){
						return;
					}
					if(obj.y>viewRec.y+viewRec.height || obj.y+obj.h < viewRec.y){
						return;
					}
					var mvp:Matrix3D = this.getWorldTransform(obj);
					mvp.append(viewMatrix);
					_context.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, mvp, true);
					_context.setTextureAt(1, obj.texture);
					_context.drawTriangles(indexBuffer, 0, 2);
				}
			}
		}
		
		public function refreshBitmap(value:BitmapData,p:Point):void
		{
			var i:int = p.x/2048;
			var j:int = p.y/2048;
			var obj:Object = _blockBitmapV[i][j];
			p.x = p.x - i*2048;
			p.y = p.y - j*2048;
			BitmapData(obj.bitmapdata).copyPixels(value,new Rectangle(0,0,value.width,value.height),p);
			Texture(obj.texture).uploadFromBitmapData(obj.bitmapdata);
		}
		
		public function set alpha(value:Number):void
		{
			this._alpha = value;
		}
		
		public function get alpha():Number
		{
			return this._alpha;
		}
		
		public function get height():Number
		{
			return this._height;
		}
		
		public function get width():Number
		{
			return this._width;
		}
		
		public function set x(value:Number):void
		{
			this._x = value;
		}
		
		public function get x():Number
		{
			return this._x;
		}
		
		public function set y(value:Number):void
		{
			this._y = value;
		}
		
		public function get y():Number
		{
			return this._y;
		}

		public function get bitmapdata():BitmapData
		{
			return _bitmapdata;
		}

		public function set bitmapdata(value:BitmapData):void
		{
			_bitmapdata = value;
			var wNum:int = Math.ceil(_bitmapdata.width/2048);
			var hNum:int = Math.ceil(_bitmapdata.height/2048);
			this._wNum = wNum;
			this._hNum = hNum;
			_blockBitmapV = new Vector.<Vector.<Object>>;
			var w:int;
			var h:int;
			var rec:Rectangle = new Rectangle();
			for(var i:int=0;i<wNum;i++){
				_blockBitmapV[i] = new Vector.<Object>;
				for(var j:int=0;j<hNum;j++){
					if(j == hNum-1){
						h = _bitmapdata.height - (hNum-1)*2048;
					}else{
						h = 2048;
					}
					
					if(i == wNum-1){
						w = _bitmapdata.width - (wNum-1)*2048;
					}else{
						w = 2048;
					}
					
					//
					var blockBit:BitmapData = new BitmapData(w,h,true,0);
					rec.x = i*2048;
					rec.y = j*2048;
					rec.height = h;
					rec.width = w;
					blockBit.copyPixels(_bitmapdata,rec,new Point);
					var blockTexture:Texture = _context.createTexture(MoleHillUtils.getTextureWH(w),MoleHillUtils.getTextureWH(h), Context3DTextureFormat.BGRA, false);
					blockTexture.uploadFromBitmapData(blockBit);
					var obj:Object = new Object;
					obj.bitmapdata = blockBit;
					obj.texture = blockTexture;
					obj.w = MoleHillUtils.getTextureWH(w);
					obj.h = MoleHillUtils.getTextureWH(h);
					obj.x = rec.x;
					obj.y = rec.y;
					_blockBitmapV[i].push(obj);
					
				}
			}
		}

		public function set url(value:String):void
		{
			_url = value;
		}


	}
}